import React, { useEffect, useRef, useState } from "react"
import { Button, Form, Toask } from "@/component/index"
import cssStyle from './index.module.css'
import moment from "moment"
import { connect } from 'react-redux'
import eventBus from '@/util/eventBus'
import socket from '@/websocket'
import imgIcon from '@/assets/images/image.png'

function App(props) {
    const msgRef = useRef()
    const [title, setTitle] = useState('')
    const [userGroup, setUserGroup] = useState('user')
    const [addFriendAccount, setAddFriendAccount] = useState('')
    const [searchFriendResult, setSearchFriendResult] = useState({
        account: '',
        name: ''
    })
    const [msg, setMsg] = useState('')
    const [msgList, setMsgList] = useState([])
    const [currentFriendAccount, setCurrentFriendAccount] = useState('')
    const [friendList, setFriendList] = useState([])
    const [currentGroup, setCurrentGroup] = useState('')
    const [groupList, setGroupList] = useState([])
    const imgLoad = src => {
        return new Promise((resolve, reject) => {
            const image = new Image()
            image.addEventListener('load', () => {
                resolve()
            })
            image.addEventListener('error', () => {
                resolve()
            })
            image.src = src
        })
    }
    const getMsg = async data => {
        try {
            if ((userGroup === 'user' && (data.sender === props.account || (data.receiver === props.account && data.sender === currentFriendAccount))) || (userGroup === 'group' && data.groupId === currentGroup)) {
                if (data.type === 'img') {
                    await imgLoad(data.content)
                }
                if (userGroup === 'user') {
                    const index = friendList.findIndex(item => {
                        return item.account === currentFriendAccount
                    })
                    friendList[index].type = data.type
                    friendList[index].lastMsg = data.content
                }
                msgList.push(data)
                setMsgList([...friendList])
                setMsgList([...msgList])
                scrollBottom()
            }
        } catch (error) {
            console.log(error)
        }
    }
    const sendMsg = ({ content, type, fileName }) => {
        let sendData = {}
        if (userGroup === 'user') {
            sendData = {
                content,
                sender: props.account,
                receiver: currentFriendAccount,
                type,
                msgType: userGroup
            }
        } else {
            sendData = {
                content,
                sender: props.account,
                groupId: currentGroup,
                type,
                msgType: userGroup
            }
        }
        if (type === 'img') {
            sendData.fileName = fileName
        }
        socket.emit('msg', sendData, (err, data) => {
            if (err) {
                console.log(err)
                return
            }
            getMsg(data)
            setMsg('')
        })
    }
    const scrollBottom = () => {
        if (msgRef.current.scrollHeight > msgRef.current.clientHeight) {
            msgRef.current.scrollTop = msgRef.current.scrollHeight
        }
    }
    const getHistoryMsg = params => {
        socket.emit('getHistoryMsg', params, (err, data) => {
            if (err) {
                console.log(err)
                return
            }
            if (data.length) {
                const promiseArr = []
                data.forEach(item => {
                    if (item.type === 'img') {
                        promiseArr.push(imgLoad(item.content))
                    }
                })
                Promise.all(promiseArr).then(() => {
                    const scrollHeight = msgRef.current.scrollHeight
                    msgList.unshift(...data)
                    setMsgList([...msgList])
                    msgRef.current.scrollTop = msgRef.current.scrollHeight - scrollHeight
                }).catch(err => {
                    console.log(err)
                })
            }
        })
    }
    const changeFriend = (account, name) => {
        if (account === currentFriendAccount) {
            return
        }
        setTitle(name)
        setMsgList([])
        setCurrentFriendAccount(account)
        socket.emit('joinRoom', {
            type: 'user',
            id: account
        }, (err, data) => {
            if (err) {
                console.log(err)
                return
            }
            const promiseArr = []
            data.forEach(item => {
                if (item.type === 'img') {
                    promiseArr.push(imgLoad(item.content))
                }
            })
            Promise.all(promiseArr).then(() => {
                setMsgList(data)
                scrollBottom()
            }).catch(err => {
                console.log(err)
            })
        })
    }
    const _searchFriend = async () => {
        socket.emit('searchFriend', {
            account: addFriendAccount
        }, (err, data) => {
            if (err) {
                console.log(err)
                return
            }
            setSearchFriendResult(data)
        })
    }
    const _addFriend = async () => {
        try {
            let toask = Toask()
            if (searchFriendResult.account === props.account) {
                toask.showToask({
                    type: 'error',
                    title: '无法添加自己为好友',
                    duration: 1500
                })
                return
            }
            socket.emit('addFriend', {
                account: addFriendAccount
            }, err => {
                if (err) {
                    console.log(err)
                    return
                }
                toask.showToask({
                    type: 'success',
                    title: '添加成功',
                    duration: 1500
                })
                queryFriendList()
            })
        } catch (error) {
            console.log(error)
        }
    }
    const queryFriendList = async () => {
        socket.emit('queryFriendList', (err, data) => {
            if (err) {
                console.log(err)
                return
            }
            if (data.length) {
                console.log(data)
                setFriendList(data)
                changeFriend(data[0].account, data[0].name)
            }
        })
    }
    const queryGroupList = async () => {
        socket.emit('queryGroupList', (err, data) => {
            if (err) {
                console.log(err)
                return
            }
            if (data.length) {
                setGroupList(data)
                changeGroup(data[0].group_id, data[0].name)
            }
        })
    }
    const scroll = e => {
        if (e.target.scrollTop === 0 && msgList.length) {
            getHistoryMsg({
                account: currentFriendAccount,
                time: msgList[0].time
            })
        }
    }
    const getFile = file => {
        if (file[0].size > 100*1024*1024) {
            let toask = Toask()
            toask.showToask({
                type: 'error',
                title: '最大上传100M文件大小',
                duration: 1500
            })
            return
        }
        sendMsg({
            content: file[0],
            type: 'img',
            fileName: file[0].name
        })
    }
    const changeGroup = (groupId, name) => {
        if (groupId === currentGroup) {
            return
        }
        setTitle(name)
        setMsgList([])
        setCurrentGroup(groupId)
        socket.emit('joinRoom', {
            type: 'group',
            id: groupId
        }, (err, data) => {
            if (err) {
                console.log(err)
                return
            }
            
            const promiseArr = []
            data.forEach(item => {
                if (item.type === 'img') {
                    promiseArr.push(imgLoad(item.content))
                }
            })
            console.log(promiseArr)
            Promise.all(promiseArr).then(() => {
                setMsgList(data)
                scrollBottom()
            }).catch(err => {
                console.log(err)
            })
        })
    }
    const toggleUserGroup = type => {
        if (type === userGroup) {
            return
        }
        setUserGroup(type)
        if (type === 'user') {
            setCurrentGroup('')
            queryFriendList()
        } else {
            setCurrentFriendAccount('')
            queryGroupList()
        }
    }
    useEffect(() => {
        queryFriendList()
    }, [])
    useEffect(() => {
        eventBus.off('msg', getMsg)
        eventBus.on('msg', getMsg)
        return () => {
            eventBus.off('msg', getMsg)
        }
    }, [getMsg])
    useEffect(() => {
        setMsgList([])
        setFriendList([])
    }, [props.account])
    return (
        <div className={ cssStyle.websocket }>
            <div className={ cssStyle.friend }>
                <div className={ cssStyle.search }>
                    <Form.input value={ addFriendAccount } onChange={ val => { setAddFriendAccount(val) } } />
                    <Button type="primary" size="small" onClick={ _searchFriend } style={{ marginLeft: '12px' }}>搜索</Button>
                </div>
                {
                    searchFriendResult.account && searchFriendResult.name
                    ?
                    <div className={ cssStyle.add }>
                        <img src={ searchFriendResult.avatar } />
                        <p>account: { searchFriendResult.account }</p>
                        <p>name: { searchFriendResult.name }</p>
                        <Button type="primary" size="small" onClick={ _addFriend } style={{ marginLeft: '12px' }}>添加</Button>
                    </div>
                    :
                    null
                }
            </div>
            <div className={ cssStyle.container }>
                <div className={ cssStyle.left }>
                    <div className={ cssStyle.userGroup }>
                        <span onClick={ () => { toggleUserGroup('user') } } className={ userGroup === 'user' ? cssStyle.active : '' }>好友</span>
                        <span onClick={ () => { toggleUserGroup('group') } } className={ userGroup === 'group' ? cssStyle.active : '' }>群组</span>
                    </div>
                    {
                        userGroup === 'user'
                        ?
                        friendList.map((item, index) => {
                            return (
                                <div key={ index } className={ cssStyle.friendItem + (currentFriendAccount === item.account ? (' ' + cssStyle.active) : '') } onClick={ () => { changeFriend(item.account, item.name) } }>
                                    <img src={ item.avatar } />
                                    <div>
                                        <p>{ item.name }</p>
                                        <span>{ item.type === 'text' ? item.lastMsg : (item.type === 'img' ? '[图片]' : '') }</span>
                                    </div>
                                </div>
                            )
                        })
                        :
                        groupList.map((item, index) => {
                            return (
                                <div key={ index } className={ cssStyle.friendItem + (currentGroup === item.group_id ? (' ' + cssStyle.active) : '') } onClick={ () => { changeGroup(item.group_id, item.name) } }>
                                    <div>
                                        <p>{ item.name }</p>
                                    </div>
                                </div>
                            )
                        })
                    }
                </div>
                <div className={ cssStyle.right }>
                    <div className={ cssStyle.msgList }>
                        <div className={ cssStyle.head }>{ title }</div>
                        <div className={ cssStyle.list } ref={ msgRef } onScroll={ scroll }>
                        {
                            msgList.map((item, index) => {
                                return (
                                    <div key={ index }>
                                        <span>{ moment(parseInt(item.time)).format('YYYY-MM-DD HH:mm:ss') }</span>
                                        <div style={{ alignSelf: item.sender === props.account ? 'flex-end' : 'flex-start' }}>
                                        {
                                            item.type === 'text'
                                            ?
                                            <p>{ item.content }</p>
                                            :
                                            (
                                                item.type === 'img'
                                                ?
                                                <img src={ item.content } />
                                                :
                                                null
                                            )
                                        }
                                        </div>
                                    </div>
                                )
                            })
                        }
                        </div>
                    </div>
                    <div className={ cssStyle.message }>
                        <div className={ cssStyle.other }>
                            <Form.upload onChange={ getFile }>
                                <img src={ imgIcon } />
                            </Form.upload>
                        </div>
                        <Form.input type="textarea" value={ msg } onChange={ val => { setMsg(val) } } className={ cssStyle.textarea } />
                        <div className={ cssStyle.btn }>
                            <Button type="primary" size="small" onClick={ () => { sendMsg({ content: msg, type: 'text' }) } }>发送</Button>
                        </div>
                    </div>
                </div>
            </div>
        </div>
    )
}

function mapStateToProps(state) {
    return {
        account: state.account
    }
}
export default connect(
    mapStateToProps
)(App)